﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using JQuery.Net.Modules;
using System.ComponentModel.Composition;
using System.Web.Configuration;
using System.Reflection;
using System.Collections.ObjectModel;
using System.IO;

namespace JQuery.Net.UI
{
    class DockSettings
        : IDockSupport
    {
        public JQNDockLocation Location { get; set; }

        public JQNDockTabAlignment TabAlignment { get; set; }
    }
    /// <summary>
    /// This class will provide the foundation for the Gadget Communication Manager(GCM) that will connect all gadget zones and
    /// facilitate communication between gadgets using client side communication and server callbacks when needed.
    /// </summary>
    [Export("GCM", typeof(IJQNPlugin))]
    public class GadgetCommunicationManager
        : IJQNPlugin
        , IGadgetZoneSettings
    {
        #region constructor
        internal GadgetCommunicationManager()
        {
            JQNConfigSection Section = (JQNConfigSection)WebConfigurationManager.GetSection(typeof(JQNConfigSection).Name);

            Dock = new DockSettings()
            {
                Location = Section.Configuration[PluginConfigSection.dock].IsNotNull(JQNDockLocation.right, (X) =>
                    (JQNDockLocation)Enum.Parse(typeof(JQNDockLocation), X.GetSettingValue(Keys.Config.Dock.location))),
                TabAlignment = Section.Configuration[PluginConfigSection.dock].IsNotNull(JQNDockTabAlignment.top, (X) =>
                    (JQNDockTabAlignment)Enum.Parse(typeof(JQNDockTabAlignment), X.GetSettingValue(Keys.Config.Dock.tab_position)))
            };
        }
        #endregion

        public struct Keys
        {
            public struct Config
            {
                public struct GCM
                {
                    public const string personalization = "personalization";
                }
                public struct Dock
                {
                    public const string location = "location";
                    public const string tab_position = "tab";
                }
            }
        }

        #region IGadgetZoneSettings Members

        public PersonalizationSupport State { get; set; }

        public IDockSupport Dock { get; set; }

        public string ZoneSettingsToJSON(IGadgetZone zone)
        {
            return String.Format(@"{{ clientID: '#{7}', id: {8}, title: '{0}', isEmpty: {9}, mode: '{1}', type: '{2}', settings: {{ dock: '{12}', isPersonalizable: {3}, showActionMenu: {4}, enableContextMenu: {5}, showZoneHeader: {6}, texts: {{ empty: '{10}' }}, icons: {{ action: '{11}' }} }} }}"
                , /*{0}*/zone.Title
                , /*{1}*/zone.Mode
                , /*{2}*/zone.Type
                , /*{3}*/zone.IsPersonalizationEnabled ? "true" : "false"
                , /*{4}*/zone.ShowActionMenu ? "true" : "false"
                , /*{5}*/zone.EnableContextMenu ? "true" : "false"
                , /*{6}*/zone.ShowZoneHeader ? "true" : "false"
                , /*{7}*/zone.ClientID
                , /*{8}*/((List<IGadgetZone>)Zones).IndexOf(zone) + 1
                , /*{9}*/(zone.Gadgets.Count() == 0).ToJSON()
                , /*{10}*/zone.EmptyZoneText
                , /*{11}*/zone.ActionIcon
                , /*{12}*/zone.Dock);
        }

        public string GadgetSettingsToJSON(IGadget gadget)
        {
            throw new NotImplementedException();
        }

        public string GlobalSettingsToJSON()
        {
            StringBuilder oSettings = new StringBuilder();

            foreach (PropertyInfo oProperty in typeof(IGadgetZoneSettings).GetProperties())
            {
                if (oProperty.Name.Eq("state"))
                {
                    oSettings.AppendFormat(" {0}: '{1}',", oProperty.Name.ToJSProper(), oProperty.GetValue(this, null));
                }
                else if (oProperty.Name.Eq("dock") && oProperty.GetValue(this, null) != null)
                {
                    oSettings.AppendFormat(" {0}: {1},", oProperty.Name.ToJSProper(), oProperty.GetValue(this, null).ToJSON());
                }
            }

            return String.Format("{{ {0} }}", oSettings.Remove(oSettings.Length - 1, 1).ToString());
        }

        #endregion

        #region IJQNPlugin Members

        public void RegisterJQNLibraryInitializer(StringWriter writer)
        {
            if (Zones.Count() == 0)
                return;

            writer.WriteLine(String.Format("\t$.gcm.initialize({0});", GlobalSettingsToJSON()));
        }

        public void RegisterJQNLibrary(ResourceManager manager, Page page)
        {
            /// we always assign this because Gadget Zones may not always be on a particular page.
            Page = page;
            /// if there are no gadget zones then we do not need to initialize the gcm
            if (Zones.Count() == 0)
                return;

            /// byte array's to store db blobs in.
            byte[]
                shared = null,
                user = null;

            /// we need to load any gadget meta data that may exist for this page in the db.
            if (Personalization != null && Personalization.LoadPersonalizationData(this, Page.Request.Url, Page.User.Identity.Name, ref shared, ref user))
            {   /// we have successfully loaded personalization data
                State = PersonalizationSupport.server;
                /// TODO:: need to finish loading the saved gadgets into there respective zones
            }
            else
            {   /// there is no DB personliation data store
                /// must depend on client local storage to remember state information
                State = PersonalizationSupport.local;
            }
        }

        #endregion

        #region properties
        private Page Page { get; set; }

        public IEnumerable<IGadgetZone> Zones
        {
            get
            {
                return Page.Controls.ByInterface<IGadgetZone>().ToList();
            }
        }

        public IEnumerable<IGadget> Gadgets
        {
            get
            {
                return Zones.SelectMany((X) => X.Gadgets).ToList();
            }
        }

        //[Import("DB", typeof(IJQNGadgetPersonalization))]
        public IJQNGadgetPersonalization Personalization
        {
            get
            {
                JQNConfigSection Section = (JQNConfigSection)WebConfigurationManager.GetSection(typeof(JQNConfigSection).Name);

                string contract = Section.Configuration[PluginConfigSection.gadget].IsNotNull((X) =>
                    X.GetSettingValue(Keys.Config.GCM.personalization));

                return contract.IsNotNullOrEmpty()
                    ? JQNModule.Composition.IsNotNull((IJQNGadgetPersonalization)null, (x) =>
                        x.GetExportOrDefault<IJQNGadgetPersonalization>(contract))
                    : null;
            }
        }
        #endregion
    }
}
